package com.hb0730.boot.admin.modules.sci.controller;

import com.alibaba.excel.EasyExcel;
import com.alibaba.excel.support.ExcelTypeEnum;
import com.hb0730.boot.admin.base.R;
import com.hb0730.boot.admin.modules.sci.model.entity.SciExportData;
import com.hb0730.boot.admin.modules.sci.model.entity.SciPaperConference;
import com.hb0730.boot.admin.modules.sci.service.SciPaperConferenceService;
import com.hb0730.boot.admin.modules.sys.system.service.SysPermissionService;
import com.hb0730.boot.admin.security.model.UserInfo;
import com.hb0730.boot.admin.security.util.SecurityUtil;
import jakarta.servlet.http.HttpServletResponse;
import lombok.RequiredArgsConstructor;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.core.io.UrlResource;
import org.springframework.http.MediaType;
import org.springframework.validation.annotation.Validated;
import org.springframework.web.bind.annotation.*;
import org.springframework.web.multipart.MultipartFile;
import org.springframework.http.ResponseEntity;
import org.springframework.http.HttpHeaders;
import org.springframework.core.io.Resource;

import java.io.*;
import java.net.MalformedURLException;
import java.net.URLEncoder;
import java.nio.charset.StandardCharsets;
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.time.LocalDate;
import java.time.LocalDateTime;
import java.time.format.DateTimeFormatter;
import java.util.*;
import java.util.zip.ZipEntry;
import java.util.zip.ZipOutputStream;

import static org.springframework.security.util.FieldUtils.getFieldValue;

@RestController
@RequestMapping("/sci/file")
//@Tag(name = "科研：论文管理：")
@RequiredArgsConstructor
public class FileController {
    private final SciPaperConferenceService sciPaperConferenceService;
    private final SysPermissionService sysPermissionService;
//    private static final Logger logger = LoggerFactory.getLogger(FileUploadController.class);

    @Value("${file.upload-dir}")
    private String uploadDir;
    @PostMapping("/upload")
    public R<String> handleFileUpload(@RequestParam("file") MultipartFile file) {
        // 1. 检查文件是否为空
        if (file.isEmpty()) {
            return R.NG("请先选择一个文件上传。");
        }

        // 获取当前用户信息
        UserInfo userInfo = SecurityUtil.getCurrentUser();
        if (userInfo == null) {
            return R.NG("用户未登录！");
        }

        // 动态生成用户专属的文件保存路径
        String userDir = uploadDir + userInfo.getDepartment() + "/" + userInfo.getNickname() + "/";
        File directory = new File(userDir);
        if (!directory.exists() && !directory.mkdirs()) {
            return R.NG("无法创建文件目录！");
        }

        // 3. 保存新文件
        String newFilePath = userDir + System.currentTimeMillis() + "_" + file.getOriginalFilename();  // 新文件名加时间戳
        try {
            file.transferTo(new File(newFilePath));
            return R.OK(newFilePath);  // 返回新文件的保存路径
        } catch (IOException e) {
//            logger.error("文件上传失败", e);  // 记录错误
            return R.NG("文件上传失败！");
        }
    }

    @GetMapping("/preview")
    public ResponseEntity<Resource> previewPDF(@RequestParam String path) throws MalformedURLException {
        // 构造 PDF 文件路径
        System.out.println(path);
        Path filePath = Paths.get(path);
        // 从路径创建资源对象
        Resource resource = new UrlResource(filePath.toUri());
        // 设置响应头，指定返回的是 PDF 文件
        HttpHeaders headers = new HttpHeaders();
        headers.setContentType(MediaType.APPLICATION_PDF);
        // 返回资源实体
        return ResponseEntity.ok()
                .headers(headers)
                .body(resource);
    }

    @PostMapping("/download")
    public ResponseEntity<Resource> downloadPDF(@RequestBody List<String> pathList) throws IOException {
        if (pathList == null || pathList.isEmpty()) {
            return ResponseEntity.badRequest().build(); // 返回 400 错误
        }

        System.out.println(pathList);

        // 如果只有一个文件，直接下载
        if (pathList.size() == 1) {
            File pdfFile = new File(pathList.get(0));
            if (!pdfFile.exists()) {
                return ResponseEntity.notFound().build(); // 返回 404 错误
            }

            Resource resource = new UrlResource(pdfFile.toURI());
            HttpHeaders headers = new HttpHeaders();
            headers.setContentType(MediaType.APPLICATION_PDF);
            String encodedFilename = URLEncoder.encode(pdfFile.getName(), StandardCharsets.UTF_8.toString());
            headers.setContentDispositionFormData("attachment", encodedFilename);
            return ResponseEntity.ok()
                    .headers(headers)
                    .body(resource);
        }

        // 如果有多个文件，打包成 ZIP 文件
        File zipFile = File.createTempFile("pdfs", ".zip");

        try (FileOutputStream fos = new FileOutputStream(zipFile);
             ZipOutputStream zos = new ZipOutputStream(fos)) {

            Set<String> addedFiles = new HashSet<>(); // 用于追踪已添加的文件名

            for (String path : pathList) {
                File pdfFile = new File(path);
                if (pdfFile.exists()) {
                    String fileName = pdfFile.getName();
                    String uniqueFileName = fileName;

                    // 检查是否已经添加过同名文件
                    int count = 1;
                    while (addedFiles.contains(uniqueFileName)) {
                        uniqueFileName = fileName.replace(".", "_" + count++ + ".");
                    }
                    addedFiles.add(uniqueFileName);

                    try (FileInputStream fis = new FileInputStream(pdfFile)) {
                        ZipEntry zipEntry = new ZipEntry(uniqueFileName);
                        zos.putNextEntry(zipEntry);

                        byte[] buffer = new byte[1024];
                        int length;
                        while ((length = fis.read(buffer)) >= 0) {
                            zos.write(buffer, 0, length);
                        }
                        zos.closeEntry();
                    }
                }
            }
        }
        // 返回 ZIP 文件作为下载
        Resource resource = new UrlResource(zipFile.toURI());
        return ResponseEntity.ok()
                .header(HttpHeaders.CONTENT_DISPOSITION, "attachment; filename=\"pdfs.zip\"")
                .contentType(MediaType.APPLICATION_OCTET_STREAM)
                .contentLength(zipFile.length())
                .body(resource);
    }



    @PostMapping(value = "/exportData")
    public void exportData( HttpServletResponse response ,@RequestBody SciExportData sciExportData) {
        System.out.println(sciExportData);
        String path = sciExportData.getPath();
        LocalDate startTime = sciExportData.getStartTime();
        LocalDate  endTime = sciExportData.getEndTime();
        String timeType = sciExportData.getTimeType();
        String sqlTableName = path.replace("/", "_");
//        String excelTableName = sysPermissionService.loadTitleByComponent(path);
        List<List<String>> head = new ArrayList<>();
        List<String> selectedFields = new ArrayList<>();
        Map<String, String>  map = sciExportData.getValues();
        try {
            this.setExcelResponseProp(response, "用户列表");
//            response.setHeader("Content-disposition", "attachment;filename*=utf-8''" + excelTableName + ".xlsx");
//            System.out.println(list);
            map.forEach((key, value) -> {
                // 将值添加到head列表中，每个值作为一个单例列表
                head.add(Collections.singletonList(value));
                // 将键添加到selectedFields列表中
                selectedFields.add(key);
            });
            System.out.println(sqlTableName);
            List<SciPaperConference> list = sciPaperConferenceService.findAll(sqlTableName,selectedFields ,startTime,endTime,timeType);
            System.out.println(list);
            List<List<String>> data = new ArrayList<>();
            for (SciPaperConference conference : list) {
                List<String> row = new ArrayList<>();
                for (String field : selectedFields) {
                    String value = null;
                    try {
                        Object fieldValue = getFieldValue(conference, field);
                        if (fieldValue instanceof String) {
                            value= (String) fieldValue;
                        } else if (fieldValue instanceof LocalDateTime) {
                            value=((LocalDateTime) fieldValue).format(DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss"));
                        } else {
                            value= fieldValue != null ? fieldValue.toString() : null;
                        }
                    } catch (IllegalAccessException e) {
                        throw new RuntimeException(e);
                    }
                    row.add(value);
                }
                data.add(row);
            }
            EasyExcel.write(response.getOutputStream())
                    .head(head)
                    .excelType(ExcelTypeEnum.XLSX)
                    .sheet("test")
                    .doWrite(data);
        } catch (IOException e) {
            throw new RuntimeException(e);
        }
    }
    private void setExcelResponseProp(HttpServletResponse response, String rawFileName) throws UnsupportedEncodingException {
        response.setContentType("application/vnd.openxmlformats-officedocument.spreadsheetml.sheet");
        response.setCharacterEncoding("utf-8");
        String fileName = URLEncoder.encode(rawFileName, "UTF-8").replaceAll("\\+", "%20");
        response.setHeader("Content-disposition", "attachment;filename*=utf-8''" + fileName + ".xlsx");
    }
    // 删除文件的接口
    @DeleteMapping("/delete")
    public R<String> deleteFile(@Validated @RequestBody String filePath) {
        System.out.println(filePath);
        filePath = filePath.replace("\"", "");
        // 校验文件路径
        if (filePath == null || filePath.isEmpty()) {
            return R.NG("文件路径不能为空");
        }
        // 根据路径创建文件对象
        File file = new File(filePath);
        // 路径是个文件且不为空时删除文件
        if (file.isFile() && file.exists()) {
            return file.delete() ? R.OK("删除成功") : R.NG("删除失败");
        }
        return R.NG("删除失败");
    }
}
